<template>
  <div class="comment-wrap">
    <div class="title">
      <div>
        <span>Comments | {{ total || 0 }} 条留言</span>
        <el-icon @click="refresh">
          <RefreshRight />
        </el-icon>
      </div>
      <LoginCpt />
    </div>
    <SortTabCpt
      :sort="sort"
      @sort-change="sortChange"
    />
    <div v-if="list.length > 0">
      <div v-loading="listLoading">
        <ItemCpt
          v-for="(item, index) in list"
          :key="index"
          :item="item"
          @handle-modal="handleModal"
          @handle-star="handleStar"
          @close-modal="closeModal"
          @show-reply="showReply"
          @delete-reply="deleteReply"
        />
        <div
          v-if="hasMore"
          class="load-more"
          @click="handleParentPage"
        >
          加载更多留言
          <el-icon><ArrowDown /></el-icon>
        </div>
        <div
          v-else
          class="load-more"
        >
          已加载所有留言~
        </div>
      </div>
    </div>
    <div
      v-else
      class="no-comment"
    >
      目前还没有人留言~
    </div>

    <ModalCpt
      v-if="currentComment"
      :title="currentComment.children_comment_total + '条回复'"
      top="20%"
      class="comment-modal-wrap"
      @close-modal="closeModal"
    >
      <template #content>
        <div class="parent">
          <ItemCpt
            :item="currentComment"
            @handle-star="handleStar"
            @show-reply="showReply"
            @delete-reply="deleteReply"
          />
        </div>

        <div
          v-loading="childListLoading"
          class="child-list-wrap"
        >
          <SortTabCpt
            :sort="modalSort"
            @sort-change="changeModalSort"
          />
          <div
            v-if="childList"
            ref="childListRef"
            class="child-list"
          >
            <ItemCpt
              v-for="(item, index) in childList"
              :key="index"
              :item="item"
              @handle-modal="handleModal"
              @handle-star="handleStar"
              @close-modal="closeModal"
              @show-reply="showReply"
              @delete-reply="deleteReply"
            />
            <div
              ref="childListHasMoreRef"
              class="has-more-observer"
            />
            <el-divider v-if="!childListHasMore">
              没有更多内容了
            </el-divider>
          </div>
        </div>
      </template>
    </ModalCpt>

    <component
      :is="currentComponent"
      :username="
        currentReplyComment ? currentReplyComment.from_user.username : ''
      "
      @close-reply="closeReply"
      @reply="handleReply"
    />
  </div>
</template>

<script lang="ts">
import { defineComponent, inject, reactive, ref, toRefs, watch, nextTick } from 'vue'
import { ElMessageBox } from 'element-plus'
import ItemCpt from './components/Item/index.vue'
import SortTabCpt from './components/SortTab/index.vue'

import LoginCpt from '@/components/Login/index.vue'
import ReplyCpt from '@/components/Reply/index.vue'
import ModalCpt from '@/components/Modal/index.vue'

import { userStore } from '@/store/user'
import { InitData } from './index'
import { deepCloneByJson } from '@/utils/index'
export default defineComponent({
  name: 'Comment',
  components: {
    LoginCpt,
    ReplyCpt,
    SortTabCpt,
    ItemCpt,
    ModalCpt
  },
  props: {
    sort: {
      type: String,
      default: ''
    },
    list: {
      type: Array,
      default: () => []
    },
    pageSize: {
      type: Number,
      default: 0
    },
    nowPage: {
      type: Number,
      default: 1
    },
    childrenPageSize: {
      type: Number,
      default: 0
    },
    hasMore: {
      type: Boolean,
      default: false
    },
    total: {
      type: Number,
      default: 0
    }
  },
  emits: {
    refresh: (payload: any) => {
      return payload
    },
    'sort-change': (payload: any) => {
      return payload
    },
    'handle-parent-page': (payload: any) => {
      return payload
    }
  },
  setup (props, { emit }) {
    const user = userStore()
    const $get:any = inject('$get')
    const $post:any = inject('$post')
    const $newmessage:any = inject('$newmessage')
    const data = reactive(new InitData())

    const childListRef = ref(null)
    const childListHasMoreRef:any = ref(null)

    watch(() => data.childListIsBottom, (newVal, oldVal) => {
      if (data.childListLoading) return
      if (newVal && data.childListHasMore) {
        data.childListParams.nowPage++
        ajaxChildComment(data.childListParams)
      }
    })

    const refresh = async () => {
      if (data.currentComment !== null) {
        data.childListParams.nowPage = 1
        await ajaxChildComment(data.childListParams)
      }
      emit('refresh', null)
    }
    const closeModal = () => {
      data.currentComment = null
    }
    const ajaxChildComment = async (params:any) => {
      try {
        data.childListLoading = true
        const commentData = await $get('comment/child_comment', params)
        if (params.nowPage === 1) {
          data.childList = commentData.rows
        } else {
          data.childList = [...data.childList, ...commentData.rows]
        }
        data.childListHasMore = commentData.hasMore
        data.childListLoading = false
      } catch (error) {
        console.log(error)
        data.childListLoading = false
      }
    }
    // 触底事件
    const touchBottom = () => {
      nextTick(() => {
        const intersectionObserver = new IntersectionObserver(
          (entries) => {
            entries.forEach((item) => {
              if (!item.isIntersecting) {
                data.childListIsBottom = false
              } else {
                data.childListIsBottom = true
              }
            })
          },
          { root: childListRef.value }
        )
        intersectionObserver.observe(childListHasMoreRef.value)
      })
    }
    // 弹窗回复数据
    const handleModal = async (v:any) => {
      const item:any = deepCloneByJson(v)
      delete item.children_comment
      data.currentComment = item
      const params = {
        article_id: item.article_id,
        nowPage: props.nowPage,
        pageSize: props.pageSize,
        orderBy: 'desc',
        orderName: props.sort === 'date' ? 'created_at' : 'star_total',
        parent_comment_id: item.id
      }
      data.childListParams = params
      await ajaxChildComment(params)
      touchBottom()
    }
    // 修改了弹窗的tab
    const changeModalSort = async (val:any) => {
      const wrap:any = childListRef.value
      wrap.scrollTo({ top: 0 })
      data.modalSort = val
      const params = {
        article_id: data.currentComment.article_id,
        nowPage: props.nowPage,
        pageSize: props.pageSize,
        orderBy: 'desc',
        orderName: val === 'date' ? 'created_at' : 'star_total',
        parent_comment_id: data.currentComment.id
      }
      data.childListParams = params
      await ajaxChildComment(params)
      touchBottom()
    }
    const sortChange = (val:any) => {
      emit('sort-change', val)
    }
    const ajaxCreateStar = async (item:any) => {
      try {
        await $post('star/create', {
          article_id: item.article_id,
          comment_id: item.id,
          to_user_id: item.from_user_id
        })
      } catch (error) {
        console.log(error)
      }
    }
    const ajaxDeleteStar = async (item:any) => {
      try {
        await $post(`star/delete/${item.is_star_id}`, {})
      } catch (error) {
        console.log(error)
      }
    }
    /**
     * 点赞
     */
    const handleStar = async (item:any) => {
      const type = item.is_star === false
      if (!user.userInfo) {
        $newmessage('暂未登录，请登录！', 'warning')
        return
      }
      if (type) {
        await ajaxCreateStar(item)
        $newmessage('点赞ok~', 'success')
      } else if (type === false) {
        await ajaxDeleteStar(item)
        $newmessage('取消点赞ok~', 'success')
      }
      refresh()
    }
    const handleParentPage = () => {
      emit('handle-parent-page', {
        nowPage: props.nowPage,
        pageSize: props.pageSize,
        orderName: props.sort === 'date' ? 'created_at' : 'star_total',
        orderBy: 'desc'
      })
    }
    // 显示回复框
    const showReply = (item:any) => {
      data.currentReplyComment = item
      data.currentComponent = 'ReplyCpt'
    }
    // 删除回复
    const deleteReply = (item:any) => {
      const msg =
        item.children_comment_total === 0
          ? '确定删除评论吗?'
          : `你的评论有${item.children_comment_total}条回复，确定删除评论吗？`
      ElMessageBox.confirm(msg, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(async () => {
          try {
            const res = await $post(`comment/delete/${item.id}`)
            $newmessage(res.message, 'success')
            refresh()
          } catch (error) {
            $newmessage(error, 'error')
          }
        })
        .catch(() => {
          $newmessage('已取消删除', 'info')
        })
    }
    // 关闭回复框
    const closeReply = () => {
      data.currentReplyComment = null
      data.currentComponent = null
    }
    // 新增回复
    const handleReply = async (content:string) => {
      try {
        await $post('comment/create', {
          article_id: data.currentReplyComment.article_id,
          content,
          parent_comment_id:
            data.currentReplyComment.parent_comment_id === -1
              ? data.currentReplyComment.id
              : data.currentReplyComment.parent_comment_id,
          reply_comment_id: data.currentReplyComment.id,
          to_user_id: data.currentReplyComment.from_user_id
        })
        $newmessage('回复成功~', 'success')
        refresh()
        closeReply()
      } catch (error) {
        console.log(error)
      }
    }
    const dataRef = toRefs(data)
    return {
      ...dataRef, childListRef, childListHasMoreRef, refresh, handleModal, closeModal, changeModalSort, sortChange, handleStar, showReply, deleteReply, closeReply, handleReply, handleParentPage
    }
  }
})
</script>

<style lang="scss" scoped>
@import '@/assets/css/constant.scss';
@import '@/assets/css/mixin.scss';

.comment-wrap {
  .title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 20px 0;
    .el-icon {
      color: $theme-color1;
      cursor: pointer;
    }
  }

  .load-more {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 50px;
    border-radius: 4px;
    background-color: $theme-color4;
    cursor: pointer;
  }

  .no-comment {
    padding: 40px 0;
    text-align: center;
  }
  .comment-modal-wrap {
    .parent {
      overflow: hidden;
      margin-top: 10px;
    }
    .child-list-wrap {
      margin-left: 30px;
      .child-list {
        overflow-y: scroll;
        min-height: 200px;
        max-height: 300px;
        @extend .hideScrollbar;

        .has-more-observer {
          width: 1px;
          height: 1px;
        }
      }
    }
  }
}
</style>
